package net.alche.fa.core.parse;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.io.FileUtil;
import net.alche.al.util.AC;
import net.alche.al.util.fa.FaQueue;
import net.alche.fa.core.FaException;
import net.alche.fa.core.model.FaValue;
import net.alche.fa.core.model.Logic;

/**
 * FavaParseLogic
 */
@SuppressWarnings("all") 
public class FavaParseLogic {
  // List<Sage> sageList = new ArrayList<>();
  ParseInfo parseInfo = new ParseInfo();
  String path = "";
  String fileName = "";
  List<RowInfo> rowInfoList = null;
  File classFile;

  public FavaParseLogic(List<RowInfo> rowInfoList) {
    this.rowInfoList = rowInfoList;
    FaKeyWord.initJav();
  }

  public FavaParseLogic(String path) {
    this.path = path;
    this.fileName = path.substring(5);
    FaKeyWord.initJav();
  }

  public FavaParseLogic(File f) {
    this.classFile = f;
    this.fileName = f.getName();
    FaKeyWord.initJav();
  }

  public void setFileName(String fileName) {
    this.fileName = fileName;
  }

  public Logic getClassLogic() throws FaException {
    List<RowInfo> rowList = this.rowInfoList;
    if (rowList == null) {
      rowList = this.parseRowList(this.path);
    }
    Logic rootLogic = new Logic();
    Map<String, Logic> parMap = new HashMap<>();
    parMap.put("-1", rootLogic);
    try {
      this.parseLogic2(rowList, this.parseInfo, parMap);
    } catch (Exception ex) {
      if (ex instanceof FaException) {
        throw (FaException) ex;
      }
      if (classFile != null)
        AC.log("error-file:" + classFile.getName());
      else
        AC.log("error-file:" + path);
      AC.log("parse-java", AC.json.toStr(rowInfoList));
      AC.log("错误行:\n" + this.parseInfo.tempRoot.getNum() + ": " + this.parseInfo.tempRoot.getCodeStr());
      ex.printStackTrace();
    }
    System.out.println("fileName="+fileName);
    if (fileName.equals("SysDeptCtrl.fa")) {
      AC.log(AC.json.toStr(rootLogic.getChild()));
      AC.log("  ");
    }
    this.toTreeLogic(rootLogic.getChild());
    if (fileName.startsWith("SysDeptCtrl")) {
      AC.log(AC.json.toStr(rootLogic.getChild()));
    }
    return rootLogic;
  }

  private void toTreeLogic(List<Logic> rowList) {
    for (Logic lv0 : rowList) {
      if (lv0.getPlus().size() > 0 && "@".equals(lv0.getPlus().get(0).getWhat())) {
        treeLogic(lv0);
      }
      if (lv0.getChild() != null) {
        for (Logic cc : lv0.getChild()) {
          treeLogic(cc);
        }
      }
    }
  }

  private void treeLogic(Logic logic) {
    Logic back = this.branch(logic.getPlus());
    if (back != null) {
      logic.setWhat(back.getWhat());
      if (back.getLogicObj() != null)
        logic.setLogicObj(back.getLogicObj());
      else {
        logic.setObj(back.getObj());
        logic.setFaObjValue(back.getFaObjValue());
      }
      if (back.getLogicData() != null)
        logic.setLogicData(back.getLogicData());
      else {
        logic.setData(back.getData());
        logic.setFaDataValue(back.getFaDataValue());
      }
      logic.setPlus(null);
    }
    if (logic.getChild() != null) {
      for (Logic cc : logic.getChild()) {
        treeLogic(cc);
      }
    }
  }

  private Logic branch(List<Logic> parList) {
    if (parList == null)
      return null;
    Logic logic = null;
    String what = "";
    int whatOperLv = -1;
    int index = -1;
    if (parList.size() == 1) {
      if (parList.get(0).getWhat() == null) {
        logic = parList.get(0);
        FaValue fav = FaKeyWord.getDataType(logic.getObj());
        logic.setFaObjValue(fav);
        return logic;
      }
    }
    for (int i = 0; i < parList.size(); i++) {
      Logic gg = parList.get(i);
      if (gg.getWhat() != null) {
        int operLv = FaKeyWord.getOperPriority(gg.getWhat());
        boolean isLarger = false;
        if (!AC.isEmpty(what) && operLv == whatOperLv && !FaKeyWord.arrContain(FaKeyWord.rightLowSytax, gg.getWhat())) {
          isLarger = true;
        } else if (operLv > whatOperLv) {
          isLarger = true;
        }
        if (isLarger) {
          what = gg.getWhat();
          index = i;
          whatOperLv = operLv;
        }
      }
    }
    // if (what != null)
    // AC.log("what= " + what);
    if (whatOperLv >= 0) {
      logic = new Logic();
      List<Logic> pList = new ArrayList<Logic>();
      List<Logic> pList2 = new ArrayList<Logic>();
      for (int i = 0; i < parList.size(); i++) {
        if (i < index) {
          pList.add(parList.get(i));
        } else if (i > index) {
          pList2.add(parList.get(i));
        }
      }
      logic.setWhat(what);
      Logic indexLogic = parList.get(index);
      if (indexLogic.getNum() != null && indexLogic.getNum() >= 0) {
        logic.setNum(indexLogic.getNum());
        // logic.setLv(indexLogic.getLv());
        logic.setCodeStr(indexLogic.getCodeStr());
      }
      // AC.log("what= " + what);
      // 分割"jav符"
      List<Logic> spList = indexLogic.getPlus();
      if (spList != null && spList.size() > 0) {
        if (",".equals(what) || ";".equals(what)) {
          logic.setLogicObj(branch(spList));
        } else {
          logic.setLogicData(branch(spList));
        }
      }
      if (pList.size() > 0) {
        Logic first = pList.get(0);
        if (pList.size() == 1) {
          // AC.log(first.getWhat());
          // AC.log(AC.json.toStr(first));
          if (first.getWhat() == null) {
            logic.setObj(first.getObj());
            FaValue fav = FaKeyWord.getDataType(logic.getObj());
            logic.setFaObjValue(fav);
          } else {
            first.setLogicObj(this.branch(first.getPlus()));
            logic.setLogicObj(first);
            first.setPlus(null);
          }
        } else {
          logic.setLogicObj(this.branch(pList));
        }
      }
      if (pList2.size() > 0) {
        Logic first = pList2.get(0);
        if (pList2.size() == 1) {
          // AC.log(first.getWhat());
          if (first.getWhat() == null) {
            logic.setData(first.getObj());
            FaValue fav = FaKeyWord.getDataType(logic.getData());
            logic.setFaDataValue(fav);
          } else {
            if (",".equals(first.getWhat()) || ";".equals(first.getWhat())) {
              first.setLogicObj(this.branch(first.getPlus()));
              // AC.log(AC.json.toStr(first.getLogicObj()));
            } else {
              first.setLogicData(this.branch(first.getPlus()));
            }
            logic.setLogicData(first);
            first.setPlus(null);
          }
        } else {
          logic.setLogicData(this.branch(pList2));
        }
      }
    }
    return logic;
  }

  public static void main2(String[] args) {
    FavaParseLogic parse = new FavaParseLogic("ctrl.SysDeptCtrl");

    try {
      parse.getClassLogic();
    } catch (FaException e) {
      e.printStackTrace();
    }
  }

  List<RowInfo> parseRowList(String path) {
    List<String> codes = null;
    if (this.classFile != null) {
      codes = FileUtil.readUtf8Lines(this.classFile);
    } else {
      codes = AC.file.readLinesClassRes("/net/alche/fa/base/java/src/" + path.replace(".", "/") + ".fa");
    }
    int lineNumber = 1;
    int lv = 0;
    boolean blank = true;
    List<RowInfo> rowList = new ArrayList<>();
    for (String code : codes) {
      if (code != null && code.equals("--##--"))
        break;
      String[] words = code.split(" ");
      lv = 0;
      blank = true;
      for (int k = 0; k < words.length; k++) {
        String word = words[k];
        String next = null;
        if (words.length > k + 1)
          next = words[k + 1];
        if (blank && words[k].equals("")) {
          lv++;
        } else if (blank && words[k].equals("\t")) {
          lv += 2;
        } else {
          if (word.startsWith("\t")) {
            lv += 2;
            word = word.substring(1);
          }
          if (blank) {
            lv /= 2;
            blank = false;
          }
          if (word.equals("//")) {
            break;
          }
          RowInfo rowInfo = new RowInfo();
          rowInfo.lv = lv;
          rowInfo.num = lineNumber;
          rowInfo.codeStr = code;
          List<String> codeWords = new ArrayList<>();
          for (int j = k; j < words.length; j++) {
            String txt = words[j].trim();
            if (txt.startsWith("`")) {
              txt = txt.substring(1);
              for (int n = k + 1; n < words.length; n++) {
                txt += " " + words[n];
              }
              codeWords.add(txt);
              break;
            }
            // AC.log(txt);
            if (!AC.isEmpty(txt)) {
              if (!FaKeyWord.isNumber(txt) && txt.contains(".") && !txt.equals(".")) {
                String[] tts = txt.split("\\.");
                boolean first = true;
                for (String t : tts) {
                  if (!first)
                    codeWords.add(".");
                  codeWords.add(t);
                  first = false;
                }
              } else
                codeWords.add(txt);
            }
            // rowInfo.words[j - k] = words[j].trim();
          }
          if (codeWords.size() > 0) {
            rowInfo.words = codeWords.toArray(new String[codeWords.size()]);
            rowList.add(rowInfo);
            // AC.log(AC.json.toStr(rowInfo.words));
          }
          // rowInfo.words = new String[words.length - k];
          // rowInfo.words[0] = word;
          break;
        }
      }
      lineNumber++;
    }
    return rowList;
  }

  // word 解析层Logic
  Logic parseLogic2(List<RowInfo> codes, ParseInfo info, Map<String, Logic> parMap) throws FaException {
    Logic root = new Logic();
    if (info.rowI >= codes.size())
      return null;
    RowInfo row = codes.get(info.rowI);
    root.setLv(row.lv);
    root.setNum(row.num);
    root.setCodeStr(row.codeStr);
    info.tempRoot = root;
    String front = "";
    String first = row.words[0];
    Logic par = parMap.get("" + (root.getLv() - 1));
    int addLogic = 1; // 1.child 2:plus 0 :none
    FaQueue<Logic> parQueue = null;
    boolean fEnd = FaKeyWord.isOperation(info.frontEndChar);
    boolean fFirst = FaKeyWord.isOperation(first);
    boolean lvIsSame = false;
    if (info.rowI > 0 && row.lv == codes.get(info.rowI - 1).lv) {
      lvIsSame = true;
    }
    boolean isLinker = false;
    if (this.rowIsLinker(info.frontEndChar, first)) {
      parQueue = info.parQueue;
      info.baseQueSize = parQueue.size();
      addLogic = 0;
    }
    // else if (!AC.isEmpty(info.frontEndChar) && !FaKeyWord.isData(first)) {
    // boolean linker = false;
    // if (lvIsSame) {
    // if ("_}".contains(info.frontEndChar)) {
    // // AC.log("not", info.frontEndChar);
    // } else if (fEnd != fFirst) {
    // linker = true;
    // if (fEnd && ")_else".contains(info.frontEndChar)) {
    // linker = false;
    // } else if (fFirst && "continue_break_(".contains(first)) {
    // linker = false;
    // } else if (FaKeyWord.isRowJav(first)) {
    // linker = false;
    // }
    // } else if (fEnd && fFirst && "(_{".contains(first)) {
    // linker = true;
    // }
    // } else if ("_{".contains(info.frontEndChar)) {
    // linker = true;
    // }
    // if (linker) {
    // parQueue = info.parQueue;
    // info.baseQueSize = parQueue.size();
    // if (!parQueue.last().hasValueData()) {
    // parQueue.last().setCodeStr(row.codeStr);
    // info.baseQueSize--;
    // }
    // addLogic = 0;
    // front = info.frontEndChar;
    // }
    // }
    if (parQueue == null) {
      parQueue = new FaQueue<>();
      parQueue.push(root);
    }
    info.tempAddType = addLogic;
    for (int i = 0; i < row.words.length; i++) {
      String word = row.words[i];
      String next = null;
      if (row.words.length > i + 1)
        next = row.words[i + 1];
      if (next == null) {
        info.frontEndChar = word;
      }
      if (word.equals(""))
        continue;
      if (word.equals("//"))
        break;
      boolean isFor = "|for|catch|".contains("|" + row.words[0] + "|");
      boolean isStatic = "static".equals(row.words[0]);
      boolean isFinal = "final".equals(row.words[0]);
      if (((i == 0 && AC.isEmpty(front)) || isFor || isStatic || isFinal)
          && !"(".equals(next)) {
        word = "var-" + word;
      }

      if (FaKeyWord.isOperation(word)) {
        if (word.equals("(") || word.equals("{") || word.equals("[")) {
          quePlus(parQueue, word);
          if (i == 0) {
            info.baseQueSize = parQueue.size();
          }
          // !FaKeyWord.isOperation(front) && FaKeyWord.isVar(front)
          if (!"[".equals(word) && (!FaKeyWord.frontNotParams(front) || "{".equals(word))) {
            quePlus(parQueue, ",");
          }
          if ("(".equals(word) && "for".equals(front)) {
            quePlus(parQueue, ";");
          }
        } else if (word.equals(")") || word.equals("}") || word.equals("]")) {
          this.checkQueueBracket(parQueue, word);
          if (i == 0) {
            info.baseQueSize = parQueue.size();
          }
        } else if (word.equals(",") || word.equals(";")) {
          this.checkQueueBracket(parQueue, word);
          quePlus(parQueue, word);
          if (i == 0) {
            info.baseQueSize = parQueue.size();
          }
        } else {
          quePlus(parQueue, word, "plus-no");
        }
      } else {
        Logic gg = quePlus(parQueue, null, "plus-no");
        gg.setObj(word);
      }
      front = word;
    }
    info.rowI++;
    parMap.put("" + row.lv, root);
    if (root.hasValueData())

    {
      if (addLogic == 1)
        par.addChild(root);
      else if (addLogic == 2)
        par.addPlus(root);
      if (addLogic > 0) {
        info.parLogic = root;
        info.parQueue = parQueue;
      }
    }

    parseLogic2(codes, info, parMap);
    return root;
  }

  final static String[] linkerWords = { ",", "+", "-", "*", "/", "%" };

  boolean rowIsLinker(String frontEnd, String first) {
    if (frontEnd == null || first == null)
      return false;
    for (String kk : linkerWords) {
      if (kk.equals(frontEnd) || kk.equals(first)) {
        return true;
      }
    }
    return false;
  }

  // Logic parseLogic(List<RowInfo> codes, ParseInfo info, Map<String, Logic>
  // parMap) throws FaException {
  // Logic root = new Logic();
  // if (info.rowI >= codes.size())
  // return null;
  // RowInfo row = codes.get(info.rowI);
  // root.setLv(row.lv);
  // root.setNum(row.num);
  // root.setCodeStr(row.codeStr);
  // info.tempRoot = root;
  // String front = "";
  // String first = row.words[0];
  // Logic par = parMap.get("" + (root.getLv() - 1));
  // int addLogic = 1; // 1.child 2:plus 0 :none
  // FaQueue<Logic> parQueue = null;
  // boolean fEnd = FaKeyWord.isOperation(info.frontEndChar);
  // boolean fFirst = FaKeyWord.isOperation(first);
  // boolean lvIsSame = false;
  // if (info.rowI > 0 && row.lv == codes.get(info.rowI - 1).lv) {
  // lvIsSame = true;
  // }
  // if (",".equals(first) || ",".equals(info.frontEndChar)) {
  // parQueue = info.parQueue;
  // info.baseQueSize = parQueue.size();
  // addLogic = 0;
  // } else if (!AC.isEmpty(info.frontEndChar) && lvIsSame) {
  // boolean linker = false;
  // if ("_}".contains(info.frontEndChar)) {
  // // AC.log("not", info.frontEndChar);
  // } else if (fEnd != fFirst) {
  // linker = true;
  // if (fEnd && ")_else".contains(info.frontEndChar)) {
  // linker = false;
  // } else if (fFirst && "(".contains(first)) {
  // linker = false;
  // } else if (FaKeyWord.isRowJav(first)) {
  // linker = false;
  // }
  // } else if (fEnd && fFirst && "(_{".contains(first)) {
  // linker = true;
  // }
  // if (linker) {
  // parQueue = info.parQueue;
  // info.baseQueSize = parQueue.size();
  // if (!parQueue.last().hasValueData()) {
  // parQueue.last().setCodeStr(row.codeStr);
  // info.baseQueSize--;
  // }
  // addLogic = 0;
  // front = info.frontEndChar;
  // }
  // }
  // if (parQueue == null) {
  // parQueue = new FaQueue<>();
  // parQueue.push(root);
  // if (!FaKeyWord.isOperation(row.words[0])) {
  // quePlus(parQueue, null);
  // }

  // }
  // info.tempAddType = addLogic;
  // for (int i = 0; i < row.words.length; i++) {
  // String word = row.words[i];
  // if (word.equals(""))
  // continue;
  // if (word.equals("//"))
  // break;
  // String next = null;
  // if (row.words.length > i + 1)
  // next = row.words[i + 1];
  // if (next == null) {
  // info.frontEndChar = word;
  // }
  // String lastWhat = parQueue.last().getWhat();
  // if (FaKeyWord.isOperation(word)) {
  // if (word.equals("(")) {
  // if (FaKeyWord.isVar(front) && parQueue.last().getWhat() == null) {
  // parQueue.last().setWhat("(");
  // quePlus(parQueue, ",");
  // } else if (parQueue.last().getWhat() == null && parQueue.last().getObj() ==
  // null) {
  // parQueue.last().setWhat("(");
  // } else {
  // quePlus(parQueue, word);
  // }
  // quePlus(parQueue, null);
  // } else if (word.equals(")") || word.equals("}") || word.equals("]")) {
  // this.checkQueueBracket(parQueue, word);
  // if (i == 0) {
  // info.baseQueSize = parQueue.size();
  // }
  // } else if (word.equals(",")) {
  // this.checkQueueBracket(parQueue, word);
  // quePlus(parQueue, word);
  // if (i == 0) {
  // info.baseQueSize = parQueue.size();
  // }
  // } else if (word.equals("[")) {
  // parQueue.pop();
  // quePlus(parQueue, word);
  // if (i == 0) {
  // info.baseQueSize = parQueue.size();
  // }
  // quePlus(parQueue, null);
  // } else if (word.equals("{")) {
  // if (lastWhat == null && parQueue.last().getObj() == null) {
  // parQueue.last().setWhat(word);
  // } else {
  // quePlus(parQueue, word);
  // }
  // quePlus(parQueue, null);
  // } else if (word.equals("?")) {
  // this.checkQueue(parQueue, word);
  // List<Logic> plus = parQueue.last().getPlus();
  // parQueue.last().setPlus(new ArrayList<>());
  // quePlus(parQueue, "?");
  // // 条件区 ?-if
  // parQueue.last().addPlus(new Logic("?-if"));
  // parQueue.last().getPlus().get(0).setPlus(plus);
  // // ? 结果1
  // quePlus(parQueue, "?-v1");
  // quePlus(parQueue, null);
  // } else if (":".equals(word)) {
  // // 2元表达式
  // if (this.checkQueueWord(parQueue, "?")) {
  // this.checkQueue(parQueue, "?");
  // parQueue.pop();
  // quePlus(parQueue, "?-v2");
  // quePlus(parQueue, null);
  // } else { // 对象定义
  // parQueue.last().setWhat(word);
  // }
  // } else if (word.equals("=>")) {
  // Logic pars = parQueue.last().getPlus().get(parQueue.last().getPlus().size() -
  // 1);
  // parQueue.last().getPlus().remove(parQueue.last().getPlus().size() - 1);
  // root = quePlus(parQueue, "=>");
  // parQueue.last().addPlus(pars);
  // } else if (FaKeyWord.isGive(word)) {
  // if (parQueue.last().getWhat().startsWith("var-"))
  // parQueue.pop();
  // quePlus(parQueue, word);
  // quePlus(parQueue, null);
  // }
  // // 强制层级
  // else if ("if_for_while_return_else-if_else_switch".contains(word)) {
  // parQueue.last().setWhat(word);
  // quePlus(parQueue, null);
  // } else {
  // // if (parQueue.last().getWhat() == null&&!".".contains(word)) {
  // // parQueue.last().setWhat(word);
  // // } else {
  // quePlus(parQueue, word);
  // // }
  // if (FaKeyWord.isMath(word)) {
  // parQueue.pop();
  // }
  // if ("||_&&".contains(word)) {
  // quePlus(parQueue, null);
  // }
  // }
  // } else {
  // // 固定数据/变量
  // if (!FaKeyWord.isData(word)) {
  // word = "\"" + word + "\"";
  // }
  // if (!parQueue.last().hasObj() && (lastWhat == null ||
  // !"(_{_,".contains(lastWhat))
  // && !FaKeyWord.isSingleJav(lastWhat)) {
  // parQueue.last().setObj(word);
  // } else {
  // quePlus(parQueue, null).setObj(word);
  // }
  // // FaKeyWord.fillDataType(parQueue.last(), word);
  // }
  // front = word;
  // }
  // info.rowI++;
  // parMap.put("" + row.lv, root);
  // if (root.hasValueData()) {
  // if (addLogic == 1)
  // par.addChild(root);
  // else if (addLogic == 2)
  // par.addPlus(root);
  // if (addLogic > 0) {
  // info.parLogic = root;
  // info.parQueue = parQueue;
  // }
  // }
  // parseLogic(codes, info, parMap);
  // return root;
  // }

  Logic quePlus(FaQueue<Logic> parQueue, String word) throws FaException {
    return quePlus(parQueue, word, "plus");
  }

  Logic quePlus(FaQueue<Logic> parQueue, String word, String type) throws FaException {
    Logic logic = new Logic(word);
    if (type.startsWith("plus")) {
      if (parQueue == null || parQueue.last() == null) {
        RowInfo rowInfo = this.rowInfoList.get(this.parseInfo.rowI);
        String wordStr = "";
        if (rowInfo.words.length > 0) {
          for (String wx : rowInfo.words) {
            wordStr += " " + wx;
          }
        }
        throw new FaException(FaException.PARSE_CODE_ERROR,
            rowInfo.num + ":" + "word = " + word + ", codes = " + wordStr);
      }
      parQueue.last().addPlus(logic);
      if (parseInfo.tempAddType == 0 && parQueue.size() == parseInfo.baseQueSize) {
        logic.setLv(parseInfo.tempRoot.getLv());
        logic.setNum(parseInfo.tempRoot.getNum());
        logic.setCodeStr(parseInfo.tempRoot.getCodeStr());
      }
    }
    if (type.equals("plus-no")) {
    } else
      parQueue.push(logic);
    return logic;
  }

  boolean checkQueueWord(FaQueue<Logic> parQueue, String word) {
    for (int i = 0; i < parQueue.size(); i++) {
      Logic last = parQueue.endIndex(i);
      if (word.equals(last.getWhat())) {
        return true;
      }
    }
    return false;
  }

  String checkQueueBracket(FaQueue<Logic> parQueue, String word) {
    String key = "";
    String findWord = word;
    switch (word) {
      case ")":
        findWord = "(";
        break;
      case "]":
        findWord = "[";
        break;
      case "}":
        findWord = "{";
        break;
    }
    // int i = 0;
    while (parQueue.has()) {
      Logic last = parQueue.last();
      // if (word.equals(")"))
      // AC.log(i++, word, findWord, last.getWhat(), last.getObj());

      if (last.getWhat() != null) {
        if (word.equals(",") || word.equals(";")) {
          if ("(".equals(last.getWhat()) || "{".equals(last.getWhat())) {
            break;
          }
        } else {
          if (findWord.equals(last.getWhat())) {
            if ("(_{_[".contains(findWord))
              parQueue.pop();
            break;
          }
        }
      }
      parQueue.pop();
    }
    return key;
  }

  String checkQueue(FaQueue<Logic> parQueue, String word) {
    String key = "";
    while (parQueue.has()) {
      Logic last = parQueue.last();
      if (last.getWhat() != null) {
        if ("(".equals(last.getWhat()))
          break;
        int priority1 = FaKeyWord.getOperPriority(last.getWhat());
        int priority2 = FaKeyWord.getOperPriority(word);
        if (priority2 > priority1) {
          parQueue.pop();
        } else {
          break;
        }
      } else {
        if ("?_||_&&".contains(word)) {
          parQueue.pop();
        } else
          break;

      }
    }
    return key;
  }

  public static class RowInfo {
    String[] words;
    String codeStr;
    int lv;
    int num;
  }

  class ParseInfo {
    int rowI = 0;
    Logic parLogic;
    FaQueue parQueue;
    String frontEndChar = "";
    Logic tempRoot;
    int tempAddType = 0;
    int baseQueSize = 0;
  }

  // void recurLog(List<Sage> logicList) {
  //   if (logicList == null)
  //     return;
  //   for (Sage g : logicList) {
  //     String txt = null;
  //     String blank = "";
  //     if (g.getPlus() != null)
  //       for (int i = 0; i < g.getPlus().size(); i++) {
  //         Sage code = g.getPlus().get(i);
  //         txt = (txt != null ? txt + " " : "") + code.getTxt();
  //       }
  //     for (int b = 0; b < g.getLv(); b++) {
  //       blank += "  ";
  //     }
  //     System.out.println(g.getNum() + " : " + blank + txt);
  //     recurLog(g.getChild());
  //   }
  // }

  public void parseAllSrc() throws FaException {
    parseAllSrc(null);
  }

  public void parseAllSrc(File path) throws FaException {
    List<File> fileList = new ArrayList<>();
    this.getFiles(path, fileList);
    for (File f : fileList) {
      // FaClassConf.classNameMap.put(f.getName().replace(".fa", ""), true);
    }
    for (File f : fileList) {
      FavaParseLogic parse = new FavaParseLogic(f);
      Logic logic = parse.getClassLogic();
      // FaClassConf faClassConf = new FaClassConf(logic);
      // FaClassConf.classMap.put(faClassConf.getName(), faClassConf);
    }
  }

  public void getFiles(File f, List<File> fileList) {
    File[] files = null;
    if (f == null)
      files = FileUtil.ls("net\\alche\\fa\\base\\java\\src");
    else {
      files = f.listFiles();
    }
    if (files != null && files.length > 0) {
      for (File ff : files) {
        if (ff.isDirectory()) {
          getFiles(ff, fileList);
        } else {
          if (ff.getName().endsWith(".fa")) {
            fileList.add(ff);
            // AC.log("file=", ff.getName(), ff.getAbsolutePath());
          }
        }
      }
    }
  }
}